home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / libsrc / c / io / doscan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  7.1 KB  |  357 lines

  1. /* This is file DOSCAN.C */
  2. /* This file may have been modified by DJ Delorie (Jan 1991).  If so,
  3. ** these modifications are Coyright (C) 1993 DJ Delorie, 24 Kirsten Ave,
  4. ** Rochester NH, 03867-2954, USA.
  5. */
  6.  
  7. /* #define _doscan _____doscan */
  8. #include <stdio.h>
  9. #include <stdlib.h>  /* for atof */
  10. #include <ctype.h>
  11. #undef _doscan
  12.  
  13. #define    SPC    01
  14. #define    STP    02
  15.  
  16. #define    SHORT    0
  17. #define    REGULAR    1
  18. #define    LONG    2
  19. #define LONGDOUBLE 4
  20. #define    INT    0
  21. #define    FLOAT    1
  22.  
  23. static int _innum(int **ptr, int type, int len, int size, FILE *iop, 
  24.                   int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), 
  25.                   int *eofptr);
  26. static int _instr(char *ptr, int type, int len, FILE *iop, 
  27.                   int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), 
  28.                   int *eofptr);
  29. static const char *_getccl(const unsigned char *s);
  30.  
  31. static char _sctab[256] = {
  32.     0,0,0,0,0,0,0,0,
  33.     0,SPC,SPC,SPC,SPC,SPC,0,0,
  34.     0,0,0,0,0,0,0,0,
  35.     0,0,0,0,0,0,0,0,
  36.     SPC,0,0,0,0,0,0,0,
  37.     0,0,0,0,0,0,0,0,
  38.     0,0,0,0,0,0,0,0,
  39.     0,0,0,0,0,0,0,0,
  40. };
  41.  
  42. static int nchars = 0;
  43.  
  44. int 
  45. _doscan(FILE *iop, const char *fmt, void **argp)
  46. {
  47.     return(_doscan_low(iop, fgetc, ungetc, fmt, argp));
  48. }
  49.  
  50. int
  51. _doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *),
  52.             const char *fmt, void **argp)
  53. {
  54.     register int ch;
  55.     int nmatch, len, ch1;
  56.     int **ptr, fileended, size;
  57.  
  58.     nchars = 0;
  59.     nmatch = 0;
  60.     fileended = 0;
  61.     for (;;) switch (ch = *fmt++) {
  62.     case '\0': 
  63.         return (nmatch);
  64.     case '%':
  65.         if ((ch = *fmt++) == '%')
  66.             goto def;
  67.         if (ch == 'n')
  68.         {
  69.           **(int **)argp++ = nchars;
  70.           break;
  71.         }
  72.         if (fileended)
  73.             return(nmatch? nmatch: -1);
  74.         ptr = 0;
  75.         if (ch != '*')
  76.             ptr = (int **)argp++;
  77.         else
  78.             ch = *fmt++;
  79.         len = 0;
  80.         size = REGULAR;
  81.         while (isdigit(ch)) {
  82.             len = len*10 + ch - '0';
  83.             ch = *fmt++;
  84.         }
  85.         if (len == 0)
  86.             len = 30000;
  87.         if (ch=='l') {
  88.             size = LONG;
  89.             ch = *fmt++;
  90.         } else if (ch=='h') {
  91.             size = SHORT;
  92.             ch = *fmt++;
  93.         } else if (ch=='L') {
  94.             size = LONGDOUBLE;
  95.             ch = *fmt++;
  96.         } else if (ch=='[')
  97.             fmt = _getccl((const unsigned char *)fmt);
  98.         if (isupper(ch)) {
  99.             /* ch = tolower(ch);
  100.             gcc gives warning: ANSI C forbids braced
  101.                 groups within expressions */
  102.             ch += 'a' - 'A';
  103.             size = LONG;
  104.         }
  105.         if (ch == '\0')
  106.             return(-1);
  107.         if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc,
  108.                &fileended) && ptr)
  109.             nmatch++;
  110.         if (fileended) {
  111.             return(nmatch? nmatch: -1);
  112.         }
  113.         break;
  114.     case ' ':
  115.     case '\n':
  116.     case '\t': 
  117.     case '\r':
  118.     case '\f':
  119.     case '\v':
  120.         while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC))
  121.             ;
  122.         if (ch1 != EOF)
  123.         {
  124.             scan_ungetc(ch1, iop);
  125.         }
  126.         nchars--;
  127.         break;
  128.  
  129.     default:
  130.     def:
  131.         ch1 = scan_getc(iop);
  132.         if (ch1 != EOF) nchars++;
  133.         if (ch1 != ch) {
  134.             if (ch1==EOF)
  135.                 return(-1);
  136.             scan_ungetc(ch1, iop);
  137.             nchars--;
  138.             return(nmatch);
  139.         }
  140.     }
  141. }
  142.  
  143. static int
  144. _innum(int **ptr, int type, int len, int size, FILE *iop,
  145.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  146. {
  147.     register char *np;
  148.     char numbuf[64];
  149.     register c, base;
  150.     int expseen, scale, negflg, c1, ndigit;
  151.     long lcval;
  152.     int cpos;
  153.  
  154.     if (type=='c' || type=='s' || type=='[')
  155.         return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len,
  156.                   iop, scan_getc, scan_ungetc, eofptr));
  157.     lcval = 0;
  158.     ndigit = 0;
  159.     scale = INT;
  160.     if (type=='e'||type=='f'||type=='g')
  161.         scale = FLOAT;
  162.     base = 10;
  163.     if (type=='o')
  164.         base = 8;
  165.     else if (type=='x')
  166.         base = 16;
  167.     np = numbuf;
  168.     expseen = 0;
  169.     negflg = 0;
  170.     while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC))
  171.         ;
  172.     if (c == EOF) nchars--;
  173.     if (c=='-') {
  174.         negflg++;
  175.         *np++ = c;
  176.         c = scan_getc(iop);
  177.         nchars++;
  178.         len--;
  179.     } else if (c=='+') {
  180.         len--;
  181.         c = scan_getc(iop);
  182.         nchars++;
  183.     }
  184.     cpos = 0;
  185.     for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) {
  186.         cpos++;
  187.         if (c == '0' && cpos == 1 && type == 'i')
  188.           base = 8;
  189.         if ((c == 'x' || c == 'X') && type == 'i' && cpos == 2)
  190.         {
  191.           base = 16;
  192.           continue;
  193.         }
  194.         if (isdigit(c)
  195.          || (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) {
  196.             ndigit++;
  197.             if (base==8)
  198.                 lcval <<=3;
  199.             else if (base==10)
  200.                 lcval = ((lcval<<2) + lcval)<<1;
  201.             else
  202.                 lcval <<= 4;
  203.             c1 = c;
  204.             if (isdigit(c))
  205.                 c -= '0';
  206.             else if ('a'<=c && c<='f')
  207.                 c -= 'a'-10;
  208.             else
  209.                 c -= 'A'-10;
  210.             lcval += c;
  211.             c = c1;
  212.             continue;
  213.         } else if (c=='.') {
  214.             if (base!=10 || scale==INT)
  215.                 break;
  216.             ndigit++;
  217.             continue;
  218.         } else if ((c=='e'||c=='E') && expseen==0) {
  219.             if (base!=10 || scale==INT || ndigit==0)
  220.                 break;
  221.             expseen++;
  222.             *np++ = c;
  223.             c = scan_getc(iop);
  224.             nchars++;
  225.             if (c!='+'&&c!='-'&&('0'>c||c>'9'))
  226.                 break;
  227.         } else
  228.             break;
  229.     }
  230.     if (negflg)
  231.         lcval = -lcval;
  232.     if (c != EOF) {
  233.         scan_ungetc(c, iop);
  234.         *eofptr = 0;
  235.     } else
  236.         *eofptr = 1;
  237.     nchars--;
  238.     if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) )/* gene dykes*/
  239.         return(0);
  240.     *np++ = 0;
  241.     switch((scale<<4) | size) {
  242.  
  243.     case (FLOAT<<4) | SHORT:
  244.     case (FLOAT<<4) | REGULAR:
  245.         **(float **)ptr = atof(numbuf);
  246.         break;
  247.  
  248.     case (FLOAT<<4) | LONG:
  249.         **(double **)ptr = atof(numbuf);
  250.         break;
  251.  
  252.     case (FLOAT<<4) | LONGDOUBLE:
  253.         **(long double **)ptr = _atold(numbuf);
  254.         break;
  255.  
  256.     case (INT<<4) | SHORT:
  257.         **(short **)ptr = (short)lcval;
  258.         break;
  259.  
  260.     case (INT<<4) | REGULAR:
  261.         **(int **)ptr = (int)lcval;
  262.         break;
  263.  
  264.     case (INT<<4) | LONG:
  265.     case (INT<<4) | LONGDOUBLE:
  266.         **(long **)ptr = lcval;
  267.         break;
  268.     }
  269.     return(1);
  270. }
  271.  
  272. static int
  273. _instr(char *ptr, int type, int len, FILE *iop,
  274.        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
  275. {
  276.     register ch;
  277.     register char *optr;
  278.     int ignstp;
  279.  
  280.     *eofptr = 0;
  281.     optr = ptr;
  282.     if (type=='c' && len==30000)
  283.         len = 1;
  284.     ignstp = 0;
  285.     if (type=='s')
  286.         ignstp = SPC;
  287.     while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp)
  288.         ;
  289.     ignstp = SPC;
  290.     if (type=='c')
  291.         ignstp = 0;
  292.     else if (type=='[')
  293.         ignstp = STP;
  294.     while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
  295.         if (ptr)
  296.             *ptr++ = ch;
  297.         if (--len <= 0)
  298.             break;
  299.         ch = scan_getc(iop);
  300.         nchars++;
  301.     }
  302.     if (ch != EOF) {
  303.         if (len > 0)
  304.         {
  305.             scan_ungetc(ch, iop);
  306.             nchars--;
  307.         }
  308.         *eofptr = 0;
  309.     } else
  310.         *eofptr = 1;
  311.     if (ptr && ptr!=optr) {
  312.         if (type!='c')
  313.             *ptr++ = '\0';
  314.         return(1);
  315.     }
  316.     return(0);
  317. }
  318.  
  319. static const char *
  320. _getccl(const unsigned char *s)
  321. {
  322.     register c, t;
  323.  
  324.     t = 0;
  325.     if (*s == '^') {
  326.         t++;
  327.         s++;
  328.     }
  329.     for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
  330.         if (t)
  331.             _sctab[c] &= ~STP;
  332.         else
  333.             _sctab[c] |= STP;
  334.     if ((c = *s) == ']' || c == '-') {    /* first char is special */
  335.         if (t)
  336.             _sctab[c] |= STP;
  337.         else
  338.             _sctab[c] &= ~STP;
  339.         s++;
  340.     }
  341.     while ((c = *s++) != ']') {
  342.         if (c==0)
  343.             return((const char *)--s);
  344.         else if (c == '-' && *s != ']' && s[-2] < *s) {
  345.             for (c = s[-2] + 1; c < *s; c++)
  346.                 if (t)
  347.                     _sctab[c] |= STP;
  348.                 else
  349.                     _sctab[c] &= ~STP;
  350.         } else if (t)
  351.             _sctab[c] |= STP;
  352.         else
  353.             _sctab[c] &= ~STP;
  354.     }
  355.     return((const char *)s);
  356. }
  357.